/*
 * Ethan Levine
 * 
 * The contents of this file are subject to the GNU General Public
 * License (GPL) v2.  The full contents of this license can be
 * found at Mathma's website, http://www.codeplex.com/mathma/license
 */

package mathma.core.simp;

import mathma.core.expr.Expression;
import mathma.core.expr.ExpressionType;

import mathma.core.form.FormulaicExpression;

import mathma.core.value.Value;

import java.util.ArrayList;
import java.util.List;

/**
 * @since 0.1.6
 * @author Ethan Levine
 */
public abstract class SimplificationAlgorithm {

    abstract protected <T extends Value> Expression<T> simplifySingle(Expression<T> expr);
    
    public <T extends Value> Expression<T> simplify(Expression<T> expr) {
        if (FormulaicExpression.class.isAssignableFrom(expr.getClass())) {
            return simplifyForm((FormulaicExpression) expr);
        } else {
            return expr;
        }
    }
    
    private <T extends Value, O extends Value> Expression<T> simplifyForm(FormulaicExpression<T, O> expr) {
        Expression<T> thisPass = simplifySingle(expr);
        if (thisPass.getExpressionType().equals(ExpressionType.FORMULAIC)) {
            List<Expression<O>> operands =
                    ((FormulaicExpression) thisPass).getOperands();
            List<Expression<O>> simpOperands = new ArrayList<Expression<O>>();
            for (Expression<O> operand : operands) {
                simpOperands.add(simplify(operand));
            }
            return ((FormulaicExpression) thisPass).newInstance(simpOperands);
        } else {
            return thisPass;
        }
    }
}
